/**
 * Copyright (c) 2012 Benjamin Kaspar
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

var w = window, d = document, POSTS_PER_PAGE = 25, Options = {};

var Readmore = Class.create({
	numPosts : 0,
	url : w.location.href,
	readPosts : [],
	title : d.title,
	unreadPosts : 0,
	siteFull : false,
	newSiteStarted : false,
	stopChecking : false,
	checkingToggledOff : false,
	didScroll : false,
	focusNewPosts : false,
	nextPageToLoad : 2,
	lastPostText : null,
	userRow : $$(".user_band")[0],
	lastPMCount : 0,

	/**
	 * Initializes the extension. Starts the event listeners and the interval
	 * for the automatic thread updating.
	 */
	initialize : function() {
		this.toggleHeadlines();

		if (Options.darkStyle) {
			$$("head")[0].insert({
				bottom : new Element("link", {
					"rel" : "stylesheet",
					"href" : chrome.extension.getURL("dark.css"),
					"type" : "text/css"
				})
			});
		}

		if (Options.jumpToLastPost) {
			$$("a[href$='pagenum=lastpage']").each(function(a) {
				a.href += "#lastpost";
			});
		}

		if (Options.listenForPM) {
			var check = function() {
				new Ajax.Request(this.url, {
					onSuccess : function(r) {
						var data = r.responseText.stripScripts(), ajaxContent = new Element("div").update(data), oldUserBand = this.userRow;
						oldUserBand.update(ajaxContent.select(".user_band")[0].innerHTML.trim());
						var msgCount = oldUserBand.select("a[href^='index.php?cont=msg']")[0].innerHTML.match(/\d+/g)[0];
						if (msgCount > 0 && this.lastPMCount != msgCount) {
							this.lastPMCount = msgCount;
							chrome.extension.sendRequest({
								method : "showNotification",
								msgCount : msgCount
							});
						}
					}.bind(this)
				});
			};

			// check every 30 seconds
			w.setInterval(check.bind(this), 30 * 1000);
		}

		// only run within a thread or when making/editing a post
		if (this.url.include("forum/thread") || this.url.include("forum/edit") || this.url.include("forum/newtopic")) {
			if (Options.postPreview) {
				this.initPostPreview();
			}

			if (Options.showExtraButtons) {
				this.initExtraButtons();
			}

			if (Options.showResetButton) {
				this.addResetButton();
			}
		}

		// only run on userstreams
		if (this.url.include("userstream")) {
			if (Options.reorderStreamTitle) {
				this.reorderTitle(true);
			}
		}

		// only run in the board list
		if (this.url.include("forum/board") && Options.updateEnabled) {
			w.setInterval(function() {
				this.checkPosts(true);
			}.bind(this), Options.updateInterval * 1000);
		}

		// only run within a thread
		if (this.url.include("forum/thread")) {
			if (Options.reorderTitle) {
				this.reorderTitle();
			}

			if (Options.ajaxSubmit) {
				this.initAjaxSubmit();
			}

			if (Options.ajaxEdit) {
				this.initAjaxEdit();
			}

			if (Options.spoilerLongPosts) {
				this.enableQuoteSpoiler();
			}

			if (Options.jumpToLastPost) {
				if (w.location.hash == "#lastpost") {
					$$("table.forum tr[class^='post']").each(function(tr) {
						if (tr.readAttribute("class") != "post_preview") {
							this.scrollToCenterOfElement(tr.identify());
						}
					}.bind(this));
				}
			}

			// add "up" image
			$$("div.floatl.m2.elf")[1].insert({
				after : new Element("img", {
					"src" : chrome.extension.getURL("icons/up.png"),
					"title" : "Nach oben",
					"id" : "imgUp"
				}).setStyle({
					"float" : "right",
					"cursor" : "pointer"
				}).observe("click", function() {
					w.scrollTo(0, 0);
				}.bind(this))
			});

			// add PM shortcuts
			this.addPMShortcuts($$("td.ten.vtop"));

			// count existing posts and do some stuff
			$$("table.forum tr").each(function(tr) {
				if (tr.readAttribute("class").include("post_") && tr.id != "previewRow") {
					this.numPosts++;
					this.readPosts.push(tr.readAttribute("class").substr(5));
					this.addPostNumber(tr);
				}
			}.bind(this));

			if (Options.infiniteScrolling) {
				d.observe("scroll", function() {
					this.didScroll = true;
				}.bind(this));

				var curPage = parseInt(this.url.toQueryParams().pagenum);
				if (!isNaN(curPage)) {
					if (this.numPosts % POSTS_PER_PAGE == 0) {
						this.nextPageToLoad = curPage + 1;
					} else {
						this.nextPageToLoad = curPage;
					}
				}

				w.setInterval(function() {
					if (this.didScroll) {
						this.didScroll = false;
						if (w.innerHeight + w.pageYOffset >= d.height) {
							this.addNextPage(this.nextPageToLoad);
						}
					}
				}.bind(this), 250);
			}

			if (Options.updateEnabled) {
				$$("table.elf.forum.p2.bogray2")[0].down("td", 1).insert({
					bottom : new Element("img", {
						"src" : chrome.extension.getURL("icons/eye.png"),
						"title" : "Threadüberwachung deaktivieren"
					}).setStyle({
						"float" : "right",
						"cursor" : "pointer"
					}).observe("click", function(ev) {
						var e = ev.findElement("img");
						this.checkingToggledOff = !this.checkingToggledOff;
						if (e.src.include("eye-half.png")) {
							e.src = chrome.extension.getURL("icons/eye.png");
							e.title = "Threadüberwachung deaktivieren";
						} else {
							e.src = chrome.extension.getURL("icons/eye-half.png");
							e.title = "Threadüberwachung aktivieren";
						}
					}.bind(this))
				}).insert({
					bottom : new Element("img", {
						"src" : chrome.extension.getURL("icons/magnifier.png"),
						"title" : "Automatisch zu neuen Posts scrollen"
					}).setStyle({
						"float" : "right",
						"cursor" : "pointer",
						"opacity" : .5,
						"marginRight" : "5px"
					}).observe("click", function(ev) {
						var e = ev.findElement("img");
						this.focusNewPosts = !this.focusNewPosts;
						if (e.getStyle("opacity") >= 1.0) {
							e.setStyle({
								"opacity" : .5
							});
						} else {
							e.setStyle({
								"opacity" : 1
							});
						}
					}.bind(this))
				});

				d.on("scroll", function(event) {
					this.unmarkNewPost();
				}.bind(this));

				d.on("mousewheel", function(event) {
					this.unmarkNewPost();
				}.bind(this));

				if (Options.infiniteScrolling) {
					w.setInterval(function() {
						this.addNextPage(this.nextPageToLoad);
					}.bind(this), Options.updateInterval * 1000);
				} else {
					w.setInterval(this.checkPosts.bind(this), Options.updateInterval * 1000);
				}
			}
		}
	},

	addPMShortcuts : function(elements) {
		elements.each(function(td) {
			var name = td.down("a", 1).innerHTML.trim(), id = td.down("a", 1).href.toQueryParams().id;
			td.down("img").insert({
				before : new Element("img", {
					"src" : chrome.extension.getURL("icons/pm.png"),
					"title" : "Nachricht an " + name + " schreiben"
				}).setStyle({
					"height" : "10px",
					"marginRight" : "3px",
					"cursor" : "pointer"
				}).observe("click", function() {
					w.location.href = "index.php?cont=msg&action=send&rcpt=" + id;
				})
			});
		});
	},

	/**
	 * Wraps the quote function to enable spoilering long posts.
	 */
	enableQuoteSpoiler : function() {
		$$("a[onclick^='getPostQuote']").each(function(a) {
			var oldFunc = a.onclick;
			a.onclick = function(ev) {
				Event.stop(ev);
				oldFunc();
				if (a.up("tr").previous("tr").down("td", 1).measure("height") >= Options.spoilerLongPostsRows) {
					var oldContent = $F("c_comment"), asynchWait = setInterval(function() {
						var cont = $F("c_comment");
						if (oldContent != cont) {
							var v = cont.splice(cont.indexOf("]") + 1, 0, "[spoiler]");
							v = v.splice(v.lastIndexOf("["), 0, "[/spoiler]");
							$("c_comment").setValue(v);
							clearInterval(asynchWait);
						}
					}, 50);
				}
			}.bind(this);
		}.bind(this));
	},

	/**
	 * Creates a submit listener for the form to use nice AJAX to submit the
	 * post.
	 */
	initAjaxSubmit : function() {
		var btnSubmit = $$("input[name='submit_thread']")[0];
		btnSubmit.up("form").writeAttribute("id", "submitForm");
		$("submitForm").observe("submit", function(event) {
			Event.stop(event);
			$("submitForm").request({
				onFailure : function(r) {
					alert("Ups, irgendwas ist schiefgelaufen.\nBitte nochmal probieren!\nDetails in der Konsole! (strg+shift+j)");
					console.log(r);
				},

				onCreate : function() {
					$("submitForm").disable();
					d.body.setStyle({
						"cursor" : "progress"
					});
					btnSubmit.setValue("Speichere Antwort...");
				}.bind(this),

				onSuccess : function(r) {
					var data = r.responseText.stripScripts(), ajaxContent = new Element("div").update(data), msg = ajaxContent.select("#content")[0].innerHTML;
					d.body.setStyle({
						"cursor" : "auto"
					});
					$("submitForm").enable();
					btnSubmit.setValue("Antwort speichern");
					if (msg.include("MSG:")) {
						alert("Deine Nachricht muss aus mindestens 3 Zeichen bestehen!");
					} else {
						this.checkPosts();
						$("submitForm").reset();
					}
				}.bind(this)
			});
		}.bind(this));
	},

	/**
	 * Scrolls the viewport to a specific element so that the element is
	 * vertically centered.
	 */
	scrollToCenterOfElement : function(elementID) {
		var element = $(elementID), height = element.measure("height"), top = element.cumulativeOffset().top, scroll = d.viewport.getScrollOffsets(), dimensions = d.viewport.getDimensions();
		if ((top + height > dimensions.height + scroll.top) || (top < dimensions.height + scroll.top)) {
			w.scrollTo(0, top + (height / 2) - (dimensions.height / 2));
		}
	},

	/**
	 * Activates inline editing of posts.
	 */
	initAjaxEdit : function() {
		$$("a[href^='index.php?cont=forum/edit&postid']").each(function(a) {
			a.onclick = function(event) {
				this._ajaxEditEvent(a, event);
			}.bind(this);
		}.bind(this));
	},

	_ajaxEditEvent : function(a, event) {
		var endEditMode = function(oldFunc) {
			var formResetBtn = $("formResetBtn");
			formResetBtn.writeAttribute("value", "Zurücksetzen");
			formResetBtn.previous("input").writeAttribute("value", "Antwort speichern").setStyle({
				"fontWeight" : "normal"
			}).onclick = function() {
				oldFunc();
			};

			if ($("threadName") != null) {
				$("threadName").remove();
			}

			formResetBtn.onclick = Prototype.emptyFunction;
		};

		Event.stop(event);
		new Ajax.Request(a.href, {
			onCreate : function() {
				d.body.setStyle({
					"cursor" : "progress"
				});
			},

			onSuccess : function(response) {
				var data = response.responseText.stripScripts(), ajaxContent = new Element("div").update(data), textContent = ajaxContent.select("#c_comment")[0].value;
				$("c_comment").value = textContent;
				this.scrollToCenterOfElement("c_comment");

				var threadName = ajaxContent.select("input[name='thread[threadtopic]']")[0], isEdit = threadName != null ? true : false;

				if (isEdit) {
					$("c_comment").up("form").insert({
						top : new Element("input", {
							"id" : "threadName",
							"size" : "60"
						}).setValue(threadName.value).setStyle({
							"marginBottom" : "5px"
						})
					});
				} else {
					if ($("threadName") != null) {
						$("threadName").remove();
					}
				}

				var btnSubmit = $$("input[name='submit_thread']")[0], oldFunc = btnSubmit.onclick;
				btnSubmit.writeAttribute("value", "Bearbeiten").setStyle({
					"fontWeight" : "bold"
				}).onclick = function(event) {
					Event.stop(event);
					new Ajax.Request("index.php?cont=forum/do_edit", {
						parameters : {
							"thread[boardid]" : ajaxContent.select("input[name='thread[boardid]']")[0].value,
							"thread[threadid]" : ajaxContent.select("input[name='thread[threadid]']")[0].value,
							"thread[threadtopic]" : isEdit ? $F("threadName") : null,
							"post[postid]" : ajaxContent.select("input[name='post[postid]']")[0].value,
							"f_uid" : ajaxContent.select("input[name='f_uid']")[0].value,
							"postnew_newposttext" : $F("c_comment")
						},

						onCreate : function() {
							d.body.setStyle({
								"cursor" : "progress"
							});
						},

						onSuccess : function(r) {
							d.body.setStyle({
								"cursor" : "auto"
							});

							endEditMode(oldFunc);
							var tr = a.up("tr").previous("tr");
							tr.down("td", 1).update(this.getPostPreview($("c_comment")));

							var date = new Date(), eDate = ("0" + date.getDate()).slice(-2), eMonth = ("0" + (date.getMonth() + 1)).slice(-2), eYear = ("" + date.getFullYear()).substr(2), eHour = ("0" + date.getHours()).slice(-2), eMinute = ("0" + date.getMinutes()).slice(-2);
							tr.down("td", 1).innerHTML += "<br><br><font size='1'><i>last edited by " + this.userRow.down("div").down("a", 1).innerHTML + " @ " + eDate + "." + eMonth + "." + eYear + " @ " + eHour + ":" + eMinute + "</i></font>";

							$("c_comment").value = "";
							this.scrollToCenterOfElement(tr.identify());
							fadeColor(tr.identify(), Options.newPostColor, "#ffffff", 10, 30, "b");
						}.bind(this),

						onFailure : function(r) {
							alert("Es ist ein Fehler beim Bearbeiten aufgetreten!\nDetails in der Konsole!");
							console.log(r);
						}

					});
				}.bind(this);

				if ($("formResetBtn") != null) {
					formResetBtn.writeAttribute("value", "Abbrechen");
					formResetBtn.onclick = function() {
						endEditMode(oldFunc);
						$("c_comment").value = "";
					};

				} else {
					this.addResetButton();
					$("formResetBtn").writeAttribute("value", "Abbrechen");
					$("formResetBtn").onclick = function() {
						endEditMode(oldFunc);
						$("formResetBtn").remove();
						$("c_comment").value = "";
					};

				}

				d.body.setStyle({
					"cursor" : "auto"
				});
			}.bind(this)
		});
	},

	/**
	 * Hides specific headlines on the start page and the right column
	 */
	toggleHeadlines : function() {
		var hideDivElements = function(e) {
			e.hide();
			var curElement = e.next("div");
			while (true) {
				if (curElement.hasClassName("spacer_n")) {
					curElement.remove();
					return;
				} else {
					curElement.hide();
					curElement = curElement.next("div");
				}
			}
		};

		var removeBrElements = function(e) {
			var curElement = e.next();
			while (true) {
				if (curElement == undefined) {
					return;
				}
				if (curElement.nodeName == "BR") {
					var thisElement = curElement;
					curElement = curElement.next();
					thisElement.remove();
				} else {
					return;
				}
			}
		};

		$("nav_schlagzeilen").select("br").invoke("remove");
		$("nav_schlagzeilen").select("a.bml").each(function(e, i) {
			if (Options.headlines[i][1] == false) {
				hideDivElements(e);
			}
		});

		if (this.url == "http://www.readmore.de/" && Options.hideNews) {
			var Categories = {
				"Anzeige" : true,
				"readmore" : true,
				"Szene" : true,
				"Coverage" : true,
				"CS:GO" : true,
				"StarCraft 2" : Options.headlines[1][1],
				"Counter-Strike" : Options.headlines[0][1],
				"Dota 2" : Options.headlines[2][1],
				"League of Legends" : Options.headlines[3][1],
				"Warcraft 3" : Options.headlines[4][1]
			};

			$$("div.main_info").invoke("hide");

			$$("span.news_typ").each(function(span) {
				var div = span.up("div.news");
				if (Categories[span.innerHTML.trim()] == false) {
					div.hide();
					removeBrElements(div);
				}
			});
		}
	},

	/**
	 * Adds a reset button after the submit button to clear/reset the post.
	 */
	addResetButton : function() {
		$$("input[type='submit']")[1].insert({
			after : new Element("input", {
				"id" : "formResetBtn",
				"type" : "reset",
				"class" : "form"
			}).setStyle({
				"marginLeft" : "5px"
			})
		});
	},

	/**
	 * Reorders the title from readmore.de > Forum > Threadtitle to Threadtitle >
	 * Forum > readmore.de
	 */
	reorderTitle : function(isStream) {
		var newTitle;
		if (isStream) {
			newTitle = $$("meta[name='description']")[0].content.gsub("»", "").trim();
		} else {
			newTitle = this.title.substr(this.title.lastIndexOf("»") + 1).trim();
			newTitle = newTitle + " » Forum » readmore.de";
		}

		d.title = newTitle;
		this.title = newTitle;
	},

	/**
	 * Initializes the post preview area. This is messy, but I was too tired
	 * when I wrote this.
	 */
	initPostPreview : function() {
		// show/hide button
		$$("input[type='submit']")[1].insert({
			after : new Element("input", {
				"type" : "button",
				"class" : "form",
				"value" : "Vorschau anzeigen"
			}).setStyle({
				"marginLeft" : "5px"
			}).observe("click", function() {
				$("previewRow").toggle();
				$("previewHeader").toggle();
				if (this.value == "Vorschau anzeigen") {
					this.value = "Vorschau verstecken";
				} else {
					this.value = "Vorschau anzeigen";
				}
			})

		});

		// the table the preview is in
		var t = new Element("table", {
			"border" : "1",
			"class" : "elf forum p2 bogray2"
		}).setStyle({
			"width" : "520px",
			"tableLayout" : "fixed"
		});

		$$("form")[1].insert({
			after : t
		}).insert({
			after : new Element("div", {
				"class" : "headline_bg headline_link left",
				"id" : "previewHeader"
			}).setStyle({
				"marginTop" : "10px"
			}).update("Postvorschau").hide()
		});

		// the row of the preview. mirrors a "post row"
		var tr = '<tr id="postPreview" class="post_preview"><td class="ten vtop" style="width: 105px;"><a name="4370211" href="javascript:void(0);">#preview</a><br><br><img src="http://goo.gl/Yczyj" title="Benutzer ist zur Zeit online" alt="online"><a class="bml" href="javascript:void(0);" title="Ikib">Ikib</a><br><br><br><br><a class="avabox" href="javascript:void(0);"><img src="http://images.readmore.de/img/user/63948.jpg" style="border: 1px solid rgb(186, 186, 186); "></a></td><td class="vtop forum" id="postPreview"></td></tr>';
		t.insert({
			bottom : tr
		});

		var user = {
			name : this.userRow.down("div").down("a", 1).innerHTML,
			avatar : this.userRow.down("img").src
		};
		tr = $("postPreview");
		tr.writeAttribute("id", "previewRow").hide();

		tr.down("td").setStyle({
			"width" : "105px"
		});
		tr.down("a").writeAttribute("href", "javascript:void(0);").update("#preview").next("img").writeAttribute("src", "http://goo.gl/Yczyj").next("a").writeAttribute("href", "javascript:void(0);").writeAttribute("title", user.name).update(user.name);
		if (tr.down("img", 1) != undefined) {
			tr.down("img", 1).up("a").remove();
		}
		tr.down("td").insert({
			bottom : new Element("a", {
				"class" : "avabox",
				"href" : "javascript:void(0);"
			}).insert({
				top : new Element("img", {
					"src" : user.avatar
				}).setStyle({
					"border" : "1px solid #bababa"
				})
			})
		});

		var children = tr.down("td").childElements().reverse();
		tr.down("td").update();
		children.each(function(e) {
			tr.down("td").insert({
				top : e
			});
		});

		tr.select("span.hgray").invoke("remove");
		tr.down("td", 1).writeAttribute("id", "postPreview").update();

		w.setInterval(function() {
			this.showPostPreview($("c_comment"));
		}.bind(this), 50);
	},

	/**
	 * Parses the BBCode of the post the user is writing and displays it.
	 */
	showPostPreview : function(element) {
		if (this.lastPostText != $F(element)) {
			this.lastPostText = $F(element);
			$("postPreview").update(this.getPostPreview(element));
		}
	},

	/**
	 * Returns the parsed HTML content of the post that is being written.
	 */
	getPostPreview : function(element) {
		var result = XBBCODE.process({
			text : $F(element)
		});
		return result.html.gsub("&#91;", "[").gsub("&#93;", "]").gsub("[hr]", "<hr/>").gsub("\n", "<br/>");
	},

	/**
	 * Adds IllDepence's "RM Extrabuttons" for more options when
	 * creating/editing a post.
	 */
	initExtraButtons : function() {
		$$("head")[0].insert({
			bottom : new Element("script", {
				"type" : "text/javascript",
				"src" : "http://tareksaier.bplaced.net/notHP/rmeb/rmeb.js"
			})
		});
	},

	/**
	 * Unmarks a post as "unread" and removes the new post's background color.
	 */
	unmarkNewPost : function() {
		$$("table.forum tr").each(function(tr) {
			if (tr.readAttribute("class").include("post") && this.isVisible(tr)) {
				if (tr.readAttribute("isNewPost") == "true") {
					tr.removeAttribute("isNewPost");
					this.unreadPosts--;
					this.updateTitle();
					fadeColor(tr.identify(), Options.newPostColor, "#ffffff", 10, 30, "b");
				}
			}
		}.bind(this));
	},

	/**
	 * Checks wether a post is fully visible inside the browser's viewport.
	 */
	isVisible : function(el) {
		var top = el.offsetTop, left = el.offsetLeft, width = el.offsetWidth, height = el.offsetHeight;

		while (el.offsetParent) {
			el = el.offsetParent;
			top += el.offsetTop;
			left += el.offsetLeft;
		}

		return (top >= window.pageYOffset && left >= window.pageXOffset && (top + height) <= (window.pageYOffset + window.innerHeight) && (left + width) <= (window.pageXOffset + window.innerWidth));
	},

	/**
	 * Updates the pages/tab title to show the unread messages.
	 */
	updateTitle : function() {
		if (this.newSiteStarted) {
			d.title = "(Neue Seite) " + this.title;
		} else {
			if (this.unreadPosts > 0) {
				d.title = "(" + this.unreadPosts + ") " + this.title;
			} else {
				d.title = this.title;
			}
		}
	},

	/**
	 * Adds the post number to the post (1-25)
	 */
	addPostNumber : function(tr) {
		tr.next("tr").down("td").down("a").insert({
			after : new Element("span").update("#" + this.numPosts).setStyle({
				"float" : "left",
				"color" : "#c2c2c2"
			})
		});
	},

	addNextPage : function(page) {
		return this.checkPosts(false, true, page);
	},

	/**
	 * Checks the current thread for new posts/new pages.
	 */
	checkPosts : function(onlyRefreshLastThreads, addPage, pageNum) {
		if ((this.newSiteStarted || this.stopChecking || this.checkingToggledOff) && !addPage) {
			return false;
		}

		if (Object.isUndefined(addPage)) {
			addPage = false;
		}

		// only one request to check for new posts
		// but we don't cap the "add a new page to the existing" requests
		if ($("imgLoading") != null && !addPage) {
			return false;
		}

		var pageURL = null;
		if (!addPage) {
			pageURL = this.url;
		} else {
			pageURL = "index.php?" + $H({
				"cont" : "forum/thread",
				"threadid" : this.url.toQueryParams().threadid,
				"pagenum" : pageNum
			}).toQueryString();
		}

		new Ajax.Request(pageURL, {
			evalJS : false,

			onCreate : function() {
				if ($("imgLoading") != null) {
					return;
				}

				$("imgUp").insert({
					after : new Element("img", {
						"src" : chrome.extension.getURL("icons/loading.gif"),
						"id" : "imgLoading"
					}).setStyle({
						"float" : "right",
						"marginRight" : "3px"
					})
				});
			},

			onSuccess : function(r) {
				var data = r.responseText.stripScripts(), ajaxContent = new Element("div").update(data);

				$("imgLoading").remove();

				if (Options.updateLastForumThreads) {
					if (Options.jumpToLastPost) {
						ajaxContent.select("a[href$='pagenum=lastpage']").each(function(a) {
							a.href += "#lastpost";
						});
					}
					var contentBox = $$(".cont_box")[1], oldContent = contentBox.innerHTML.trim(), newContent = ajaxContent.select(".cont_box")[1].innerHTML.trim();
					if (oldContent != newContent) {
						fadeColor(contentBox.identify(), Options.newPostColor, "#ffffff", 10, 30, "b");
						contentBox.update(newContent);
					}
				}

				if (onlyRefreshLastThreads) {
					var oldList = $$("table.elf.p2.bogray2")[0], newList = ajaxContent.select("table.elf.p2.bogray2")[0];
					if (oldList.innerHTML.trim() != newList.innerHTML.trim()) {
						oldList.update(newList.innerHTML.trim());
					}

					return;
				}

				$(ajaxContent).select("table.forum tr").each(function(tr) {
					var trClass = tr.readAttribute("class"), trID = 0;

					if (trClass.include("post") && tr.id != "previewRow") {
						trID = trClass.substr(5);
					} else {
						return;
					}

					// add new post
					if ((addPage && this.readPosts.indexOf(trID) == -1) || (this.readPosts.indexOf(trID) == -1 && !this.siteFull)) {
						this.readPosts.push(trID);
						this.numPosts++;

						// only mark as new if the poster != self
						if (tr.down("td").down("a.bml").title != this.userRow.down("div").down("a", 1).innerHTML) {
							this.unreadPosts++;
							tr.writeAttribute("isNewPost", "true");
							tr.setStyle({
								"backgroundColor" : Options.newPostColor
							});
						}

						var footerTr = tr.next("tr"), a = footerTr.down("a", 1);

						// add post number relative to this thread
						this.addPostNumber(tr);

						// add pm shortcut
						this.addPMShortcuts(tr.select("td.ten.vtop"));

						// enable ajax edit if enabled
						if (Options.ajaxEdit) {
							a.onclick = function(event) {
								this._ajaxEditEvent(a, event);
							}.bind(this);
						}

						$$("table.forum")[0].insert({
							bottom : tr
						}).insert({
							bottom : footerTr
						});

						if (this.focusNewPosts) {
							this.scrollToCenterOfElement(tr.identify());
						}
					} else {
						// post already existed. check for changes
						var postID = this.readPosts[this.readPosts.indexOf(trID)], rowID = "post_" + postID, oldPost = $$("." + rowID)[0].down("td", 1), newPost = ajaxContent.select("." + rowID)[0].down("td", 1);
						if (newPost.textContent.trim() != oldPost.textContent.trim()) {
							oldPost.update(newPost.innerHTML.trim());
							fadeColor(oldPost.identify(), Options.newPostColor, "#ffffff", 10, 30, "b");
						}
					}
				}.bind(this));

				// update title to show new posts/page
				this.updateTitle();

				if (addPage && (this.numPosts % POSTS_PER_PAGE == 0)) {
					this.nextPageToLoad++;
				}

				if (!addPage) {
					if (this.numPosts == POSTS_PER_PAGE) {
						this.siteFull = true;

						var oldPages = $$("div.floatl.m2.elf"), newPages = $(ajaxContent).select("div.floatl.m2.elf");
						if (newPages[0].lastDescendant().hasAttribute("href")) {
							this.stopChecking = true;
						}

						if (this.url.toQueryParams().pagenum == "lastpage") {
							var newPage = newPages[0].down("b").innerHTML, oldPage = oldPages[0].down("b").innerHTML;
							if (newPage > oldPage) {
								this.newSiteStarted = true;
							}
						} else {
							if (oldPages[0].innerHTML.trim() != newPages[0].innerHTML.trim()) {
								this.newSiteStarted = true;
							}
						}

						// update title and navigation if a new site exists
						if (this.newSiteStarted) {
							this.updateTitle();
							oldPages.each(function(e) {
								e.update(newPages[0]);
							});
						}
					}

					if (this.newSiteStarted && $("maxPostMsg") != null) {
						$("maxPostMsg").update("Eine neue Seite wurde erstellt.");
					}

					if ($("maxPostMsg") == null && this.siteFull) {
						$$("table.forum")[0].insert({
							after : new Element("h2", {
								"id" : "maxPostMsg"
							}).setStyle({
								"color" : "white",
								"backgroundColor" : "#2B91FF",
								"padding" : "3px"
							})
						});
						if (this.stopChecking) {
							$("maxPostMsg").update("Du bist nicht auf der aktuellsten Seite. Threadüberwachung beendet.");
						} else {
							$("maxPostMsg").update("Maximale Postanzahl erreicht. Neue Posts gelangen auf eine neue Seite.");
						}
					}
				}
			}.bind(this)
		});
	}

});

chrome.extension.sendRequest({
	method : "getOptions"
}, function(response) {
	Object.extend(Options, response.data);
	new Readmore();
});

Element.addMethods({
	lastDescendant : function(element) {
		element = $(element).lastChild;
		while (element && element.nodeType != 1) {
			element = element.previousSibling;
		}
		return $(element);
	}

});

String.prototype.splice = function(idx, rem, s) {
	return (this.slice(0, idx) + s + this.slice(idx + Math.abs(rem)));
};
